package com.lanchetech.common.util;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 通用object工具包
 *
 */
public class ObjectUtil {

	private  static final Logger logger = LoggerFactory.getLogger(ObjectUtil.class);

	private ObjectUtil() {
	}

	/**
	 * 对象copy
	 *
	 * @param source
	 * @param target
	 * @param <T>
	 * @return
	 */
	public static <T> T copy(Object source, Class<T> target) {
		try {
			if (null != source) {
				T t = target.newInstance();
				BeanUtils.copyProperties(source, t);
				return t;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 对象copy
	 *
	 * @param list
	 * @param target
	 * @param <S>
	 * @param <T>
	 * @return
	 */
	public static <S, T> List<T> copy(List<S> list, Class<T> target) {
		List<T> returnList = new ArrayList<>();		
		try {
			if (CollectionUtils.isNotEmpty(list)) {
				for (Object source : list) {
					if (null != source) {
						T t = target.newInstance();
						BeanUtils.copyProperties(source, t);
						returnList.add(t);
					}
				}
			}			
			return returnList;
		} catch (Exception e) {
			logger.error("List复制发生异常", e);
//			throw new UtilException("List复制发生异常");
		}
		return null;
	}

	/**
	 * map转换成object
	 *
	 * @param map
	 * @param beanClass
	 * @return
	 * @throws Exception
	 */
	public static Object mapToObject(Map<String, Object> map, Class<?> beanClass){
		Assert.notNull(map, "mapToObject中map不可以为null");
		try {
			Object obj = beanClass.newInstance();
			Field[] fields = obj.getClass().getDeclaredFields();
			for (Field field : fields) {
				int mod = field.getModifiers();
				if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
					continue;
				}
				field.setAccessible(true);
				field.set(obj, map.get(field.getName()));
			}
			return obj;
		}catch(Exception e) {
			logger.error("mapToObject发生异常：{}",e);
			//throw new UtilException("mapToObject发生异常：{}");
		}
		return null;
	}

	/**
	 * object转换成map
	 *
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> objectToMap(Object obj){
		Assert.notNull(obj, "objectToMap中obj不可以为null");
		try {
			Map<String, Object> map = new HashMap<>();
			Field[] declaredFields = obj.getClass().getDeclaredFields();
			for (Field field : declaredFields) {
				field.setAccessible(true);
				map.put(field.getName(), field.get(obj));
			}
			return map;
		}catch(Exception e) {
			logger.error("objectToMap 方法发生异常：{}",e);
			//throw new UtilException("objectToMap 方法发生异常：{}");
		}
		return null;
	}

	/**
	 * 调用对象get方法
	 *
	 * @param object
	 * @param fieldName
	 * @return
	 */
	public static Object getValue(Object object, String fieldName) {
		try {
			StringBuilder sb = new StringBuilder();
			sb.append("get").append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1));
			Method method = object.getClass().getMethod(sb.toString());
			method.setAccessible(false);
			return method.invoke(object);
		} catch (Exception e) {
			logger.error("getValue方法发生异常：{}",e);
		}
		return null;
	}

	/**
	 * 调用对象set方法
	 *
	 * @param object
	 * @param fieldName
	 * @param value
	 * @return
	 */
	public static void setValue(Object object, String fieldName, Object value) {
		String str = "";
		try {
			StringBuilder sb = new StringBuilder();
			sb.append("set").append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1));
			str = sb.toString();
			Method method = object.getClass().getMethod(str, value.getClass());
			method.setAccessible(false);
			method.invoke(object, value);
		} catch (Exception e) {
			logger.error("setValue 发生异常：{}",e);
			//throw new UtilException("setValue 发生异常：{}");
		}
	}

	/**
	 * Object 对象转 List
	 */
	public static <T> List<T> castList(Object obj, Class<T> clazz) {
		List<T> result = new ArrayList<T>();
		if (obj instanceof List<?>) {
			for (Object o : (List<?>) obj) {
				result.add(clazz.cast(o));
			}
			return result;
		}
		return null;
	}
}
